mcp: add client-side OAuth flow#544
Merged
samthanawalla merged 5 commits intomodelcontextprotocol:mainfrom Sep 30, 2025
Merged
Conversation
This is a preliminary implementation of OAuth 2.1 for the client. It provides an http.RoundTripper, auth.HTTPTransport, that invokes a user-provided callback of type auth.OAuthHandler. The latter is responsible for all the OAuth work. We will add code to make that easier in later PRs. Much remains to be done : Dynamic client registration is not implemented. Since it is optional, we also need another way of supplying the client ID and secret to this code. Resource Indicators, as described in section 2.5.1 of the MCP spec. And, of course, tests. We should test against fake implementations but also, if we can find any, real reference implementations.
jba
requested changes
Sep 30, 2025
c12efd0 to
a2c7f17
Compare
jba
previously approved these changes
Sep 30, 2025
a2c7f17 to
8f3713d
Compare
Contributor
|
Let's not submit until after the release.
…On Tue, Sep 30, 2025, 10:34 AM Sam Thanawalla ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In auth/client.go
<#544 (comment)>
:
> + return resp, nil
+ }
+ if _, ok := base.(*oauth2.Transport); ok {
+ // We failed to authorize even with a token source; give up.
+ return resp, nil
+ }
+
+ resp.Body.Close()
+ // Try to authorize.
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ // If we don't have a token source, get one by following the OAuth flow.
+ // (We may have obtained one while t.mu was not held above.)
+ if _, ok := t.opts.Base.(*oauth2.Transport); !ok {
+ authHeaders := resp.Header[http.CanonicalHeaderKey("WWW-Authenticate")]
+ ts, err := t.handler(req.Context(), OAuthHandlerArgs{
Done
------------------------------
In go.mod
<#544 (comment)>
:
> @@ -1,6 +1,8 @@
module github.com/modelcontextprotocol/go-sdk
-go 1.23.0
+go 1.24.0
Done
—
Reply to this email directly, view it on GitHub
<#544 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AENAOZKQNJW6RLLWIA22MDT3VKIG7AVCNFSM6AAAAACH2NKQZ6VHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZTEOBVGI4TSNJXHA>
.
You are receiving this because your review was requested.Message ID:
***@***.***>
|
8f3713d to
5e8bfda
Compare
Open
jba
approved these changes
Sep 30, 2025
rumpl
reviewed
Oct 17, 2025
| } | ||
| t.opts.Base = &oauth2.Transport{Base: t.opts.Base, Source: ts} | ||
| } | ||
| return t.opts.Base.RoundTrip(req.Clone(req.Context())) |
There was a problem hiding this comment.
In cagent we use the same trick for OAuth. I just spent the morning debugging and fixing our code for streamable mcp servers and thought I'd tell you what was wrong, might be useful for you.
This second request that comes after the oauth flow has a half-broken request, the body of the request was already read by the first call on line 70, so you would get a 400 Bad Request back from the server. You need to hold on the original body and put it back here before sending a second RoundTrip.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is a preliminary implementation of OAuth 2.1 for the client.
When a StreamableClientTransport encounters a 401 Unauthorized response
from the server, it initiates the OAuth flow described in thec
authorization section of the MCP spec
(https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization).
On success, the transport obtains an access token which it passes
to all subsequent requests.
Much remains to be done here:
Resource Indicators, as described in section 2.5.1 of the MCP spec.
All of this is unexported, so it is available only to our own
StreamingClientTransport. We should add API so people can use it
with their own transports.
And, of course, tests. We should test against fake implementations
but also, if we can find any, real reference implementations.
For #19
Co-authored-by: Jonathan Amsterdam jba@google.com